package com.library.librarybackend.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.library.librarybackend.domain.ResponseWithPage;
import com.library.librarybackend.domain.constant.GlobalConstant;
import com.library.librarybackend.domain.dto.*;
import com.library.librarybackend.domain.entity.Attachment;
import com.library.librarybackend.domain.entity.Book;
import com.library.librarybackend.domain.enums.AttachmentEnum;
import com.library.librarybackend.domain.enums.BookFormatEnum;
import com.library.librarybackend.domain.enums.SortTypeEnum;
import com.library.librarybackend.domain.vo.AttachmentVO;
import com.library.librarybackend.domain.vo.BookVO;
import com.library.librarybackend.handler.exception.BusinessException;
import com.library.librarybackend.service.AttachmentService;
import com.library.librarybackend.service.BookService;
import com.library.librarybackend.mapper.BookMapper;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author MR
 * @description 针对表【book(书籍表)】的数据库操作Service实现
 * @createDate 2025-09-21 15:06:48
 */
@Slf4j
@Setter
@Service
@RequiredArgsConstructor
public class BookServiceImpl extends ServiceImpl<BookMapper, Book>
        implements BookService {

    private final AttachmentService attachmentService;

    @Override
    @Transactional
    public BookVO upload(BookUploadFormDTO bookUploadFormDTO) {
        // 添加书籍
        Book book = BeanUtil.copyProperties(bookUploadFormDTO, Book.class);
        save(book);
        BookVO bookVO = BeanUtil.copyProperties(book, BookVO.class);
        // 上传封面
        if (null != bookUploadFormDTO.getCoverFile()) {
            try {
                AttachmentVO cover = attachmentService.upload(AttachmentUploadDTO.
                        builder()
                        .ownerType(AttachmentEnum.BOOK_COVER.getValue())
                        .ownerId(book.getId())
                        .path(GlobalConstant.BOOK_COVER)
                        .file(bookUploadFormDTO.getCoverFile())
                        .isPrivate(false)
                        .build()
                );
                lambdaUpdate()
                        .eq(Book::getId, book.getId())
                        .set(Book::getCoverUrl, cover.getUrl())
                        .update();
                bookVO.setCoverUrl(cover.getUrl());
            } catch (Exception e) {
                throw new BusinessException("上传封面失败", e);
            }
        }
        // 上传书籍文件
        MultipartFile file = bookUploadFormDTO.getBookFile();
        // 判断文件格式
        if (!BookFormatEnum.isExist(StrUtil.subAfter(file.getOriginalFilename(), ".", true).toUpperCase(Locale.ROOT))) {
            throw new BusinessException("请上传pdf、epub、txt格式书籍文件");
        }
        try {
            AttachmentVO bookFile = attachmentService.upload(AttachmentUploadDTO
                    .builder()
                    .ownerType(AttachmentEnum.BOOK_FILE.getValue())
                    .ownerId(book.getId())
                    .path(GlobalConstant.BOOK_FILE)
                    .file(file)
                    .isPrivate(true)
                    .build()
            );
            bookVO.setBookFile(bookFile);
        } catch (Exception e) {
            throw new BusinessException("上传书籍失败", e);
        }
        return bookVO;
    }

    @Override
    public ResponseWithPage<BookVO> queryPage(BookQueryDTO bookQueryDTO) {
        if (!SortTypeEnum.isExist(bookQueryDTO.getSortType())) {
            throw new BusinessException("排序方式不存在");
        }
        Page<?> page = bookQueryDTO.toPage();
        // 查询书籍
        IPage<BookVO> bookVOIPage = baseMapper.queryPage(page, bookQueryDTO);
        List<Long> list = bookVOIPage.getRecords().stream().map(BookVO::getId).toList();
        if (list.isEmpty()) {
            return ResponseWithPage.of(bookVOIPage);
        }
        // 查询书籍文件并按照书籍id分组
        Map<Long, AttachmentVO> collect = attachmentService
                .lambdaQuery()
                .eq(Attachment::getOwnerType, AttachmentEnum.BOOK_FILE.getValue())
                .in(Attachment::getOwnerId, list)
                .list()
                .stream()
                .map(attachment -> BeanUtil.copyProperties(attachment, AttachmentVO.class))
                .collect(Collectors.toMap(AttachmentVO::getOwnerId, attachment -> attachment, (existing, replacement) -> existing));
        // 填充书籍文件
        bookVOIPage.getRecords().forEach(bookVO -> bookVO.setBookFile(collect.get(bookVO.getId())));
        return ResponseWithPage.of(bookVOIPage);
    }

    @Override
    public InputStream download(Long id, String objName) {
        InputStream inputStream = attachmentService.download(objName);
        lambdaUpdate()
                .eq(Book::getId, id)
                .setIncrBy(Book::getDownloadCount, 1)
                .update();
        return inputStream;
    }
}




